/*
 * SyncResource.java
 *
 * Created on April 12, 2007, 1:39 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.atomojo.auth.service.app;

import java.sql.SQLException;
import java.util.UUID;
import java.util.logging.Level;
import org.atomojo.app.client.XMLRepresentationParser;
import org.atomojo.auth.service.db.AuthDB;
import org.atomojo.auth.service.db.Permission;
import org.atomojo.auth.service.db.Role;
import org.atomojo.auth.service.db.XML;
import org.infoset.xml.Document;
import org.infoset.xml.Element;
import org.infoset.xml.util.DocumentDestination;
import org.restlet.Request;
import org.restlet.data.CharacterSet;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ServerResource;

/**
 *
 * @author alex
 */
public class RoleResource extends ServerResource
{
   
   AuthDB db;
   XMLRepresentationParser parser = XML.createParser();
   String name;
   String suuid;
   String permissionId;
   String permissionName;
   /** Creates a new instance of SyncResource */
   public RoleResource() {
      setNegotiated(false);
   }

   protected void doInit() {
      db = (AuthDB)getRequest().getAttributes().get(AuthApplication.DB_ATTR);
      parser.addAllowedElement(XML.PERMISSION_NAME);
      name = AuthApplication.getStringAttribute(getRequest(),"name",null);
      suuid = AuthApplication.getStringAttribute(getRequest(),"uuid",null);
      permissionId = AuthApplication.getStringAttribute(getRequest(),"pid",null);
      permissionName = AuthApplication.getStringAttribute(getRequest(),"pname",null);
   }
   
   public Representation get()
   {
      try {
         Role role = fetch();
         if (role!=null) {
            if (permissionId!=null) {
               getContext().getLogger().info("Getting permission "+permissionId+" for role {"+role.getUUID()+"}"+role.getName());
               // check for permission by id
               try {
                  UUID id = UUID.fromString(permissionId);
                  Permission p = db.getPermission(id);
                  if (p==null) {
                     getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                     return new StringRepresentation("Permission does not exist.");
                  } else if (!role.hasPermission(p)) {
                     getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                     return new StringRepresentation("Role does not have the permission.");
                  } else {
                     getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
                     return null;
                  }
               } catch (SQLException ex) {
                  getContext().getLogger().log(Level.SEVERE,"Error retrieving permission "+permissionId,ex);
                  getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
                  return new StringRepresentation("Exception during processing, see logs.");
               } catch (IllegalArgumentException ex) {
                  getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                  return new StringRepresentation("Bad UUID value "+permissionId);
               }
            } else if (permissionName!=null) {
               // check for permission by name
               try {
                  Permission p = db.getPermission(permissionName);
                  if (p==null) {
                     getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                     return new StringRepresentation("Permission does not exist.");
                  } else if (!role.hasPermission(p)) {
                     getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                     return new StringRepresentation("Role does not have the permission.");
                  } else {
                     getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
                     return null;
                  }
               } catch (Exception ex) {
                  getContext().getLogger().log(Level.SEVERE,"Error retrieving permission "+permissionName,ex);
                  getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
                  return new StringRepresentation("Exception during processing, see logs.");
               }
            } else {
               Representation entity = new DBObjectRepresentation(MediaType.APPLICATION_XML,role);
               entity.setCharacterSet(CharacterSet.UTF_8);
               return entity;
            }
         } else {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
            return null;
         }
      } catch (SQLException ex) {
         getContext().getLogger().log(Level.SEVERE,"Cannot get Role from database.",ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Exception during processing, see logs.");
      }
   }
   
   public Representation post(Representation entity)
   {
      if (!XMLRepresentationParser.isXML(entity.getMediaType())) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("Non-XML media type for entity body: "+entity.getMediaType().getName());
      }
      Document doc = null;
      
      try {
         
         DocumentDestination dest = new DocumentDestination();
         parser.parse(entity,dest);
         doc = dest.getDocument();
      } catch (Exception ex) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("XML parse error: "+ex.getMessage());
      }
      
      try {
         Role role = fetch();
         Element top = doc.getDocumentElement();
         String sid = top.getAttributeValue("id");
         String name = top.getAttributeValue("name");
         Permission p = null;
         if (sid!=null) {
            p = db.getPermission(UUID.fromString(sid));
         }
         if (name!=null) {
            p = db.getPermission(name);
         }
         if (p==null) {
            getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            return new StringRepresentation("Cannot find permission.");
         } else {
            role.addPermission(p);
            getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
            return null;
         }
      } catch (SQLException ex) {
         getContext().getLogger().log(Level.SEVERE,"Error while adding permission to role.",ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Exception during processing, see logs.");
      }
      
   }
   
   protected Role fetch()
      throws SQLException
   {
      Role role = null;
      if (name!=null) {
         role = db.getRole(name);
      }
      if (suuid!=null) {
         UUID id = UUID.fromString(suuid);
         role = db.getRole(id);
      }
      return role;
   }
   
   public Representation delete() {
      try {
         Role role = fetch();
         if (role!=null) {
            if (permissionId!=null) {
               // delete for permission by id
               try {
                  UUID id = UUID.fromString(permissionId);
                  Permission p = db.getPermission(id);
                  if (p==null || !role.hasPermission(p)) {
                     getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                  } else {
                     role.removePermission(p);
                     getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
                  }
                  return null;
               } catch (SQLException ex) {
                  getContext().getLogger().log(Level.SEVERE,"Error deleting permission "+permissionId,ex);
                  getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
                  return new StringRepresentation("Database error retrieving permission, see logs.");
               } catch (IllegalArgumentException ex) {
                  getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                  return new StringRepresentation("Bad UUID value "+permissionId);
               }
            } else if (permissionName!=null) {
               // delete for permission by name
               try {
                  Permission p = db.getPermission(permissionName);
                  if (p==null || !role.hasPermission(p)) {
                     getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                  } else {
                     role.removePermission(p);
                     getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
                  }
                  return null;
               } catch (SQLException ex) {
                  getContext().getLogger().log(Level.SEVERE,"Error deleting permission "+permissionName,ex);
                  getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
                  return new StringRepresentation("Database error retrieving permission, see logs.");
               }
            } else {
               role.delete();
               getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
               return null;
            }
         } else {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
            return new StringRepresentation("Role was not found.");
         }
      } catch (IllegalArgumentException ex) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("Bad UUID value specified: "+ex.getMessage());
      } catch (SQLException ex) {
         getContext().getLogger().log(Level.SEVERE,"Database error during user delete: "+ex.getMessage(),ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Exception during processing, see logs.");
      }
   }
  
}
